/// <reference path="../Scripts/vue.js" />

(function (v) {

    if (!Vue.error) {
        Vue.erorr = function (msg) {
            alert(msg);
        }
    }

    //自定义元素数据
    function MyEleData(tp, isMiner) {
        this.type = tp;
        switch (tp) {
            default:
            case "container":
                //假定工具栏高度 2em; 1em:图标大小，1em:padding (如果要将工具栏放到背景图内，需要修改此样式)
                this.style = "position:relative;width:100%;height:calc(100% - 2em);margin-top:2em;";
                break;
            case "tools":
                if (isMiner)
                    this.style = "position:absolute;top:-2em;height:2em;background:#DEDEDE;width:100%;text-align:right;line-height:2em;z-index:1;";
                else
                    this.style = "position:absolute;top:-2em;height:2em;background:#DEDEDE;width:100%;text-align:right;line-height:2em;z-index:2;";

                break;
            case "bg":
                this.style = "position:absolute;left:0;right:0;top:0;bottom:0;width:100%;height:100%;";
                break;
            case "canvas":
                this.style = "position:absolute;z-index:1;left:0;right:0;top:0;bottom:0;width:100%;height:100%;";
                break;
        }
        return this;
    };

    //自定义块区数据
    function MyAreaData(isMiner) {
        this.container = new MyEleData("container", isMiner);
        this.bg = new MyEleData("bg", isMiner);
        this.canvas = new MyEleData("canvas", isMiner);
        this.tools = new MyEleData("tools", isMiner);
        return this;
    }

    function extend() {
        // 默认不进行深拷贝
        var deep = false;
        var name, options, src, copy, clone, copyIsArray;
        var length = arguments.length;
        // 记录要复制的对象的下标
        var i = 1;
        // 第一个参数不传布尔值的情况下，target 默认是第一个参数
        var target = arguments[0] || {};
        // 如果第一个参数是布尔值，第二个参数是 target
        if (typeof target == 'boolean') {
            deep = target;
            target = arguments[i] || {};
            i++;
        }
        // 如果target不是对象，我们是无法进行复制的，所以设为 {}
        if (typeof target !== "object" && !isFunction(target)) {
            target = {};
        }

        // 循环遍历要复制的对象们
        for (;i < length;i++) {
            // 获取当前对象
            options = arguments[i];
            // 要求不能为空 避免 extend(a,,b) 这种情况
            if (options != null) {
                for (name in options) {
                    // 目标属性值
                    src = target[name];
                    // 要复制的对象的属性值
                    copy = options[name];

                    // 解决循环引用
                    if (target === copy) {
                        continue;
                    }

                    // 要递归的对象必须是 plainObject 或者数组
                    if (deep && copy && (isPlainObject(copy) ||
                            (copyIsArray = Array.isArray(copy)))) {
                        // 要复制的对象属性值类型需要与目标属性值相同
                        if (copyIsArray) {
                            copyIsArray = false;
                            clone = src && Array.isArray(src) ? src : [];

                        } else {
                            clone = src && isPlainObject(src) ? src : {};
                        }

                        target[name] = extend(deep, clone, copy);

                    } else if (copy !== undefined) {
                        target[name] = copy;
                    }
                }
            }
        }

        return target;
    };

    function trigger(ele, e) {
        var eve = new Event(e, { "bubbles": false, "cancelable": true });
        ele = ele || document;
        if (!!ele.dispatchEvent) {
            return ele.dispatchEvent(eve);
        }
        else {
            return ele.fireEvent(eve);
        };
    }

    var toolIcons = {
        mouse: "fa-mouse-pointer", maximize: "fa-window-maximize", "minimize": "fa-window-minimize"
        , remove: "fa-remove", pencil: "fa-pencil"
        , text: "fa-font", color: "fa-circle-o", bgColor: "fa-circle", "size": "fa-pencil-square", "eraser": "fa-eraser", "clear": "fa-recycle"
        , "undo": "fa-undo", "redo": "fa-repeat"
        , font: "", "italic": "fa-italic", "bold": "fa-bold",
    };

    var languages = {
        tips: {
            noProperty: "没有属性值/No property"
            , del: "确认是否删除本画布/Area you sure to remove this canvas?"
            , canvasHasInited: "画布已存在/The canvas already exists!"
            , clickToPopMode: "点击进入涂鸦模式/Click into Graffiti Mode!"
            , presupposed: "预设/Presupposed"
            , size: "请输入正确的数值（0-100）/Please enter a correct number between 0 and 100!"
        }
        , colors: {
            black: "黑色/Black"
            , red: "红色/Red"
            , gray: "灰色/Gray"
            , green: "绿色/Green"
            , yellow: "黄色/Yellow"
            , blue: "蓝色/Blue"
            , white: "白色/White"
            , opacity: "透明/Opacity"
        }
        , buttons: {
            yes: "是/Yes"
            , confirm: "确定/Confirm"
            , no: "否/No"
            , cancel: "取消/Cancel"
        }
        , tools: {
            text: "文本工具/Text"
            , pencil: "画笔工具/Pencil"
            , eraser: "橡皮檫/Eraser"
            , undo: "撤销/Undo"
            , redo: "重做/Redo"
            , clear: "清除/Clear"
            , color: "颜色/Color"
            , bgColor: "背景色/Background color"
            , size: "画笔粗细/Width"
            , del: "移除/Remove"
            , mouse: "鼠标/Mouse"
            , maximize: "大图/Big picture"
            , minimize: "小图/Small picture"
            , remove: "删除/Remove"
        }
        , fonts: {
            bold: "加粗/Bold"
            , italic: "斜体/Italic"
            , 'delete': "删除线/Delete line"
            , 'underline': "下划线/Under line"
            , xinSong: "新宋体/SimSun"
            , kaiti: "楷体/Kai Ti"
            , yaHei: "微软雅黑/Ya Hei"
            , aril: "等线体/Arial"
            , mingLiu: "细明体/MingLiU"
            , pt: "磅/pt"
            , px: "像素/px"
            , mm: "毫米/mm"
            , '42pt': "初号/42pt"
            , '36pt': "小初/36pt"
            , '26.25pt': "一号/26.25pt"
            , '24pt': "小一/24pt"
            , '21.75pt': "二号/21.75pt"
            , '18pt': "小二/18pt"
            , '15.75pt': "三号/15.75pt"
            , '15pt': "小三/15pt"
            , '14.25pt': "四号/14.25pt"
            , '12pt': "小四/12pt"
            , '10.5pt': "五号/10.5pt"
            , '9pt': "小五/9pt"
            , '7.5pt': "六号/7.5pt"
            , '6.75pt': "小六/6.75pt"
            , '5.25pt': "七号/5.25pt"
        }
    };

    var fontFamilies = [{ name: "xinSong", value: "SimSun" }, { name: "kaiti", value: "KaiTi" }, { name: "yaHei", value: "'Microsoft YaHei'" }, { name: "aril", value: "'Arial Unicode MS'" }, { name: "mingLiu", value: "MingLiU-ExtB" }]
    var fontSizes = ['42pt', '36pt', '26.25pt', '24pt', '21.75pt'
        , '18pt', '15.75pt', '15pt', '14.25pt', '12pt'
        , '10.5pt', '9pt', '7.5pt', '6.75pt', '5.25pt']

    v.component("v-canvas-tool", {
        props: {
            "readonly": { default: false }
            , tool: String
            , lang: { required: true, type: Object }
            , isMiner: { required: true, type: Boolean }
            , _style: { default: "width:400px;height:auto;position:absolute;right:0;top:2em;z-index:4;background:#fff;cursor:defalut;padding:1em;color:black;" }
            , value: { default: "" }
            , padding: { default: "0.5em" }
        },
        data: function () {
            return {
                actived: false
                , isHover: false
                , myValue: null
                , colors: []
                , error: false
                , realValue: this.value
            }
        },
        template: [
                '<span v-bind:class="getClass()" v-bind:style="getStyle()" v-bind:title="getTitle()" '
                , ' v-on:click.prevent.self="exec($event)" v-on:mouseover="hover(true,$event)" '
                , ' v-on:canvas-blur="blur($event)" v-on:mouseout="hover(false,$event)" >'
                , '<div v-bind:class="getToolMenuCls()" v-bind:style="_style" v-if="tool==\'size\' ||tool==\'color\' || tool==\'bgColor\'" v-show="actived"'
                , ' >'
                    , '<div style="text-align:left;font-size:large;font-weight:bold;margin-top:1em;margin-bottom:1em;"><span v-html="getTitle()"></span><span>:</span></div>'

                            , '<div class="input-group" v-if="tool==\'size\'">'
                                , '<input class="form-control" v-model="myValue" type="number" express="_size" v-bind:style="getInputStyle()" min=0 max=100 v-on:keypress.enter="confirm($event)"/>'
                                , '<span class="input-group-addon" v-html="lang.fonts.mm" style="line-height:2;"></span>'
                            , '</div>'

                            , '<div class="input-group"  v-if="tool==\'color\' || tool==\'bgColor\'">'
                                , '<input class="form-control" v-model="myValue" type="text" v-bind:style="getInputStyle()" v-on:keypress.enter="confirm($event)"/>'
                                , '<select class="input-group-addon" style="line-height:2;" v-on:change="changeMyValue($event)">'
                                , '<option v-html="lang.tips.presupposed" value="#f00"></option>'
                                , '<option v-for="color in colors" v-bind:value="color.name" v-html="color.title" v-bind:style="{color:color.name,backgroundColor:color.bg}"></option>'
                                , '</select>'
                            , '</div>'

                            , '<div style="margin-top:1em;">'
                                , '<button type="button" class="btn btn-sm btn-primary" v-html="lang.buttons.confirm" v-on:click="confirm($event)"></button>'
                                , '&nbsp;&nbsp;'
                                , '<button type="button" class="btn btn-sm btn-default" v-html="lang.buttons.cancel" v-on:click="cancel($event)"></button>'
                            , '</div>'
                    , '</div>'
                , '</div>'
                , '</span>'
        ].join("")
        , methods: {
            getClass: function () {
                var cls = ["canvas-tool", "fa", 'canvas-tool-' + this.tool]
                switch (this.tool) {
                    default:
                        var d = toolIcons[this.tool];
                        cls.push(d);
                        break;
                }
                if (this.actived)
                    cls.push("actived");
                return cls.join(" ");
            }
            , getTitle: function () {
                return this.lang.tools[this.tool] || this.tool;
            }
            , getStyle: function () {
                var cls = ["padding:" + this.padding + ";cursor:pointer;"];
                if (this.readonly) {
                    switch (this.tool) {
                        case "mouse":
                        case "maximize":
                        case "minimize":
                            break;
                        case "remove":
                        case "clear":
                            cls.push("color:red");
                            break;
                        default:
                            cls.push("display:none");
                            break;
                    }
                }
                else {
                    switch (this.tool) {
                        case "remove":
                        case "clear":
                            cls.push("color:red");
                            break;
                    }
                }
                if (this.actived)
                    cls.push("background:#efefef");
                if (this.isHover)
                    cls.push("background:#fee");
                if (this.tool == "color" || this.tool == "bgColor")
                    cls.push("color:" + this.value);
                return cls.join(";");
            }
            , exec: function (e) {
                if (this.readonly) return;
                this.$emit("_event", e);
                var ele = e.target.parentElement.querySelector(".actived");
                trigger(ele, "canvas-blur");
                Vue.set(this, "actived", true);
                this.$emit("canvas-cover", !!e.target.children.length);
            }
            , blur: function (e) {
                Vue.set(this, "actived", false);
            }
            , hover: function (flag, e) {
                Vue.set(this, "isHover", !!flag);
            }
            , getToolMenuCls: function () {
                return ["canvas-tool-", this.tool].join("")
            }
            , changeMyValue: function (e) {
                Vue.set(this, "myValue", e.target.value);
            }, getInputStyle: function () {
                if (this.error)
                    return 'background:#cba;color:#f00;';
                return "";
            }
            , _size: function (ele) {
                var value = this.myValue, value2 = parseFloat(value);
                if (/^\s*\d+(\.\d+)?\s*$/.test(value) && value2 > 0 && value2 < 100) {
                    Vue.set(this, "error", false);
                    return true;
                }
                Vue.set(this, "error", true);
                Vue.erorr(this.lang.tips["size"])
                return false;
            }
            , cancel: function (e) {
                Vue.set(this, "actived", false);
            }, confirm: function (e) {
                var ele = this.$el.querySelector("input,select");
                var express = ele.getAttribute("express");
                if (!!express) {
                    var caller = this[express];
                    if (typeof (caller) != 'function')
                        throw ['Please code a function ', express, '(ele){//code here},return a boolean!'].join(" ");
                    if (caller(ele) === false) {
                        return;
                    }
                }
                Vue.set(this, "realValue", this.myValue);
                //Vue.set(this, "realValue", this.myValue); 无效，并不会改变canvas对应的值
                this.$emit("change", [this.tool, this.realValue]);
            }
        }
        , created: function () {
            switch (this.tool) {
                case "width":
                    if (!this.realValue)
                        this.realValue = "5";
                    break;
                case "bgColor":
                    this.colors = [{ name: "opacity", title: this.lang.colors["opacity"], bg: "#fff" }
                        , { name: "black", title: this.lang.colors["black"], bg: "#fff" }
                        , { name: "red", title: this.lang.colors["red"], bg: "#fff" }
                        , { name: "gray", title: this.lang.colors["gray"], bg: "#fff" }
                        , { name: "green", title: this.lang.colors["green"], bg: "#fff" }
                        , { name: "yellow", title: this.lang.colors["yellow"], bg: "#999" }
                        , { name: "blue", title: this.lang.colors["blue"], bg: "#fff" }
                        , { name: "white", title: this.lang.colors["white"], bg: "#666" }
                    ];
                    if (!this.realValue)
                        this.realValue = "opacity";
                    break;
                case "color":
                    this.colors = [{ name: "black", title: this.lang.colors["black"], bg: "#fff" }
                        , { name: "red", title: this.lang.colors["red"], bg: "#fff" }
                        , { name: "gray", title: this.lang.colors["gray"], bg: "#fff" }
                        , { name: "green", title: this.lang.colors["green"], bg: "#fff" }
                        , { name: "yellow", title: this.lang.colors["yellow"], bg: "#999" }
                        , { name: "blue", title: this.lang.colors["blue"], bg: "#fff" }
                        , { name: "white", title: this.lang.colors["white"], bg: "#666" }
                    ];
                    if (!this.realValue)
                        this.realValue = "red";
                    break;
            }
            //防止直接修改了值,而导致cancel无效，因此，使用myValue暂时接收
            this.myValue = this.realValue;
        }
    });

    v.component("v-canvas-text", {
        props: {
            "readonly": { default: false }
            , lang: { required: true, type: Object }
            , _style: { default: "width:100%;height:4em;position:absolute;left:0;top:0;z-index:2;opacity:0.6;overflow:hidden;" }
            , current: { type: Object, reqired: true }
        },
        data: function () {
            return {
                curData: this.current
                , fonts: fontFamilies
                , sizes: fontSizes
                , styles: ["bold", "italic", "deleteline", "underline"]
                , maxerContainerStyle: null
            }
        },
        template: [
            //由于打字时 光标跟随输入位置，会存在以下问题：1.样式有差异（Canvas上的字和HTML的字不是完全对等的！），导致实际位置与输入时的位置有偏差  2.不好处理透明边框效果
            //因此，文字输入框悬浮置顶
                '<div v-on:show="resetPosition()" v-bind:style="_style" class="canvas-text-box">'
                , '<div class="canvas-text-tools" style="height:2em;line-height:2em;text-align:right;background:#EFF0EF;">'
                , '<select class="font-family" v-model="curData.font.family" v-on:change="writeLine($event)">'
                , '<option v-for="item in fonts" v-html="lang.fonts[item.name]" v-bind:value="item.value"></option>'
                , '</select>'
                , '<select class="font-size" v-model="curData.font.size"  v-on:change="writeLine($event)">'
                , '<option v-for="item in sizes" v-html="lang.fonts[item]" v-bind:value="item"></option>'
                , '</select>'
                , '<span v-for="item in styles" v-bind:class="getToolClass(item)" '
                , ' v-bind:style="getToolStyle(item)" v-on:click.stop.prevent="checkTool(item)" v-bind:title="getTitle(item)"></span>'
                , '</div>'
                , '<textarea style="width:100%;height:2em;overflow-x:hidden;overflow-y:auto;" '
                , ' v-model="curData.text.value" class="canvas-text-content" '
                , ' v-on:keyup="writeLine($event)"></textarea>'
                , '<span v-bind:style="getCurStyle()" class="canvas-text-height">&nbsp;</span>'
                , '</div>'
        ].join("")
        , methods: {
            getToolClass: function (item) {
                var cls = ["canvas-text-tool", "fa"];
                switch (item) {
                    case "bold":
                        cls.push("fa-bold");
                        break;
                    case "italic":
                        cls.push("fa-italic");
                        break;
                    case "deleteline":
                        cls.push("fa-strikethrough");
                        break;
                    case "underline":
                        cls.push("fa-underline");
                        break;
                }
                if (this.curData.font[item])
                    cls.push("actived");
                return cls.join(" ");
            }
            , getTitle: function (item) {
                return this.lang.fonts[item] || item;
            }
            , getToolStyle: function (item) {
                var cls = ["padding:calc(0.5em - 2px);cursor:pointer;border:1px solid #EFF0EF;border-collapse:collapse;width:2em;"];
                if (!!this.curData.font[item]) {
                    cls.push("background:#def");
                    cls.push("border-color:#cdf");
                }
                else {
                    cls.push("border-color:#EFF0EF");
                }
                return cls.join(";");
            }
            , checkTool: function (tool) {
                var value = !this.curData.font[tool];
                Vue.set(this.curData.font, tool, value);
                this.writeLine();
            }
            , writeLine: function () {
                this.$emit("write", this.current.text.value);
            }, getCurStyle: function () {
                var s = this, font = this.curData.font;
                var style = ["font-family:", font.family
                    , ";font-size:", font.size
                    , ";font-weight:", font.bold ? "bold" : "normal"
                    , ";font-style:", font.italic ? "italic" : "normal"
                    , ";text-decoration:"
                        , font.underline && font.deleteline ? "underline line-through" : font.underline ? "underline" : font.deleteline ? "line-through" : "unset"
                ].join("");
                var needWrite = !!this.$el && !!this.$el["hasInited"];
                s.$nextTick(function () {
                    var ele = s.$el.querySelector(".canvas-text-height");
                    Vue.set(s.curData.font, "height", Math.max(ele.scrollHeight, ele.offsetHeight));
                    if (needWrite) {
                        //让画布重新绘制，防止内容背景不匹配
                        s.writeLine();
                    }
                });
                return style;
            }
        }
        , created: function () {

        },
        mounted: function () {
            this.$el["hasInited"] = true;
        }
    });


    var defaultEmptyPNG = "";
    //纯黑色图片
    //
    var defaultPNG=
        //花格子图片
        "";

    v.component("v-canvas", {
        props: {
            "src": {type:String,default:defaultPNG}
            , width: { default: "auto" }
            , height: { default: "auto" }
            , tools: { type: Array, default: () =>["mouse", "pencil", "size", "text", "color", "bgColor", "eraser", "undo", "redo", "clear", "minimize"] }
            , "scale-width": { default: "90%" }
            , "scale-height": { default: "90%" }
            , "readonly": { default: false }
            , "value": { default: defaultEmptyPNG }
            , "icon-style": { default: "padding:0.5em;hover:'opacity:0.7'" }
            , "miner-tools": { type: Array, default: () =>["maximize", "remove"] }
        }
        ,
        data: function () {
            var lang = (function () {
                if (window["vCanvas.lang"])
                    return extend({}, languages, window["vCanvas.lang"]);
                else
                    return extend({}, languages);
            })();
            return {
                lang: lang
                ,
                disposed: false
                ,
                //缩略图
                miner: new MyAreaData(true)
                    ,
                maxer: new MyAreaData(false)
                ,
                current: {
                    toolValue: {
                        // 存储当前各工具的值
                        color: "#f00"
                        , bgColor: "white"
                        ,
                        //画笔粗细(mm)
                        size: 3
                        , mouse: ""
                        , pencil: ""
                        , text: ""
                        , eraser: ""
                        , undo: ""
                        , redo: ""
                        , clear: ""
                        , minimize: ""
                        , maximize: ""
                    }
                    ,
                    //当前工具，不能使用_.current.tool，否则，无法监听
                    tool: {
                        //上一个工具
                        last: ""
                        ,
                        //当前工具的名称
                        name: ""
                        ,
                        //已经激活工具(鼠标在画布内点击过)
                        actived: false
                        ,
                        //正激活着呢（鼠标一直处于在画布中按下的状态）
                        isActive: false
                        ,
                        //激活工具的坐标
                        position: {
                            x: null
                            , y: null
                        }
                        ,
                        //激活的时候历史记录的步数
                        activedHistoryIndex: 0
                    }
                    ,
                    //历史记录
                    histories: []
                    ,
                    historyIndex: 0
                    ,
                    font: {
                        family: "'Arial Unicode MS'"
                        , size: "10.5pt"
                        , bold: false
                        , italic: false
                        , "deleteline": false
                        , height: 21
                    }
                    , text: {
                        style: ""
                        , value: ""
                    }
                    , pen: {
                        style: "solid" //solid 实线
                    }
                    , isPopup: false
                    ,
                    canvas: {
                        //当前画布的尺寸 (px)
                        size: {
                            width: 800
                            , height: 600
                        }
                    }
                }
                ,
                myValue: this.value
                ,
                maxerContainerStyle: ""
            };
        }
        , template: [
            , '<div class="vue-canvas" v-if="!disposed">'
                , '<div class="canvas-miner canvas-container" v-bind:style="{position:\'relative\',width:width,height:height,\'margin-top\':\'2em\'}">'
                    , '<div class="canvas-tools" v-bind:style="miner.tools.style">'
                    , '<v-canvas-tool v-for="(item,index) in minerTools" v-bind:key="index" v-bind:tool="item" v-bind:lang="lang" '
                    , ' v-bind:readonly="readonly" v-bind:is-miner="true" v-on:_event="exec(item,true,$event)" v-bind:value="current.toolValue[item]"'
                    , ' v-on:change="changeToolValue($event)"></v-canvas-tool>'
                    , '</div>'
                    , '<img v-bind:src="src" class="canvas-bg" v-bind:style="{position:\'absolute\',width:width,height:height,left:0,right:0,top:0,bottom:0}" v-on:load="loadedPicture($event)"/>'
                    , '<img class="canvas-content" v-bind:src="value" v-bind:style="miner.canvas.style" v-bind:title="lang.tips.clickToPopMode" v-on:click="exec(\'maximize\',$event)" />'
                , '</div>'
                , '<div class="canvas-maxer" v-show="current.isPopup" style="position:absolute;left:0;right:0;top:0;bottom:0;width:100%;height:100%;z-index:1">'
                    , '<div class="canvas-cover" style="width:100%;height:100%;background:#666;opacity:0.7;" v-on:click.self="exec(\'minimize\',$event)"></div>'
                    , '<div class="canvas-container" v-bind:style="maxer.container.style" >'
                    // 在工具栏展开时，遮住当前画布  存在bug:当工具栏的 input 元素获取焦点时，这个遮罩会自动消失
                     //, '<div class="canvas-tool-cover" style="width:100%;height:100%;background:#666;opacity:0.7;position:absolute;left:0;top:0;z-index:2" '
                     //   ,' v-show="current.tool.cover" v-on:click.self="deActiveTool(false,$event)"></div>'
                        , '<v-canvas-text v-show="current.tool.actived&&(current.tool.name==\'text\')"  '
                        , 'v-bind:current="current" v-bind:lang="lang" '
                        , ' v-on:write="writeWord($event)"></v-canvas-text>'
                        , '<div class="canvas-tools" v-bind:style="maxer.tools.style">'
                            , '<v-canvas-tool v-for="(item,index) in tools" v-bind:key="index" v-bind:tool="item" v-bind:lang="lang" '
                            , ' v-bind:readonly="readonly" v-bind:is-miner="false" '
                            , ' v-on:_event="exec(item,false,$event)" v-on:canvas-cover="cover($event)" '
                            , ' v-bind:value="current.toolValue[item]" v-on:change="changeToolValue($event)"></v-canvas-tool>'
                        , '</div>'
                        , '<img v-bind:src="src" class="canvas-bg" v-bind:style="maxer.bg.style"/>'
                        , '<canvas class="canvas-content" v-bind:style="maxer.canvas.style" '
                        , ' v-on:mousedown.prevent="mouseDown($event)" v-on:mousemove="mouseMove($event)" '
                        , 'v-on:mouseup="mouseUp($event)" v-on:mouseout="mouseUp($event)"'
                         , '/>'
                    , '</div>'
                , '</div>'
            , '</div>'
        ].join("")
        , methods: {
            loadedPicture: function (e) {
                var s = this;
                var el = s.$el.querySelector(".canvas-miner.canvas-container");
                var style = el.getAttribute("style");
                if (s.height == "auto") {
                    var height = getComputedStyle(e.target).height;
                    style = [style, ";height:", height].join("");
                };
                if (s.width == "auto") {
                    var width = getComputedStyle(e.target).width;
                    style = [style, ";width:", width].join("");
                };
                el.setAttribute("style", style);
                trigger(this.$el, "loaded");
            }
            , exec: function (tool, isMiner, e) {
                var caller = this["_" + tool];
                if (!isMiner) {
                    Vue.set(this.current.tool, "last", this.current.tool.name || "");
                    Vue.set(this.current.tool, "name", tool);
                    Vue.set(this.current.tool, "actived", false);
                }
                if (trigger(this.$el, ["before", tool].join("-")) == false)
                    return;
                if (typeof (caller) == "function") {
                    caller(isMiner, e);
                }
                else {
                    //不用特殊处理
                }
            }, changeToolValue: function (paras) {
                Vue.set(this.current.toolValue, paras[0], paras[1]);
                this.useLastTool();
            }
            , deActiveTool: function (isMiner, e) {
                if (isMiner) {
                    trigger(e.target, "canvas-blur");
                }
                else {
                    var tool = this.tools[0];
                    Vue.set(this.current.tool, "name", tool);
                    var ele = e.target.parentElement.querySelector([".canvas-tool-", tool].join(""));
                    trigger(e.target, "canvas-blur");
                    if (!!ele) {
                        trigger(ele, "click");
                    }
                }
            }
            ,
            useLastTool: function () {
                var ele = this.$el.querySelector(".canvas-tool-" + this.current.tool.last);
                if (!!ele) {
                    setTimeout(function () {
                        trigger(ele, "click");
                    }, 100);
                }
            }, cover: function (flag) {
                Vue.set(this.current.tool, "cover", !!flag);
            }
            , getLocation: function (e) {
                /// <summary>获取鼠标在画布的坐标</summary>             
                var pos = {
                    x: e.offsetX
                    , y: e.offsetY
                };
                if (e.offsetX == undefined) {
                    top.console.log("e.offsetX is undefined!");
                    var off = $(e.target).offset();
                    if (e.originalEvent.targetTouches[0] == undefined) {
                        pos.x = pos.y = 0
                    }
                    else {
                        pos.x = e.originalEvent.targetTouches[0].pageX - off.left;
                        pos.y = e.originalEvent.targetTouches[0].pageY - off.top;
                    }
                }
                top.console.log(["location:", JSON.stringify(pos)].join(""));
                return pos;
            }
            ,
            //点下鼠标:触发工具
            mouseDown: function (e) {
                if (!!this.current.tool.name) {
                    var pos = this.getLocation(e);
                    this.current.tool.position.x = pos.x;
                    this.current.tool.position.y = pos.y
                    Vue.set(this.current.tool, "isActive", true);
                    Vue.set(this.current.tool, "actived", true);
                    Vue.set(this.current.tool, "activedHistoryIndex", this.current.historyIndex);
                    var name = ["begin", this.current.tool.name].join("-");
                    var caller = this[name];
                    if (typeof (caller) == "function") {
                        caller(e);
                    }
                    trigger(this.$el, name);
                }
            }
            ,
            //鼠标移动:使用工具
            mouseMove: function (e) {
                if (!this.current.tool.isActive) return;
                var name = ["run", this.current.tool.name].join("-");
                var caller = this[name];
                if (typeof (caller) == "function") {
                    caller(e);
                }
                trigger(this.$el, name);
            }
            ,
            //鼠标弹起/移出:使用完毕
            mouseUp: function (e) {
                if (!this.current.tool.isActive) return;
                Vue.set(this.current.tool, "isActive", false);
                var name = ["end", this.current.tool.name].join("-");
                var caller = this[name];
                if (typeof (caller) == "function") {
                    caller(e);
                }
                trigger(this.$el, name);
            }
            ,
            getCVS: function () {
                if (!this.$el)
                    return window["console"] && typeof (window["console"]["log"]) == "function" && window["console"]["log"]("Not inited,please change your code to wait!")
                var ele = this.$el.querySelector("canvas.canvas-content");
                if (!ele)
                    throw 'Can not find canvas element!';
                return ele.getContext("2d");
            }
            ,
            //开始绘制线条
            beginWriteLn: function (pos) {
                var cvs = this.getCVS();
                cvs.beginPath();
                cvs.moveTo(pos.x, pos.y);
                cvs.strokeStyle = this.current.toolValue.color;
                cvs.shadowColor = this.current.toolValue.bgColor || this.current.toolValue.color;
                cvs.lineWidth = this.getPenPxSize();

            }
            ,
            //绘制线条
            writeLine: function (pos) {
                var cvs = this.getCVS();
                cvs.lineTo(pos.x, pos.y);
                cvs.stroke();
            }
            ,
            //写入文本
            writeWord: function (value) {
                var cvs = this.getCVS();
                this.restoreHistoryAuto();
                cvs.width = cvs.canvas.width;
                cvs.height = cvs.canvas.height;
                var font = this.current.font;
                cvs.font = [
                    /*
     * font参数的值分为
     * font-style: normal(正常), italic(斜体字), oblique(倾斜字体) 后两种在网页端一般没什么区别
     * font-variant: normal(正常), small-caps(英文小写字母变成小的大写)
     * font-weight: normal(正常), bold(加粗) 100-900(一般不用)
     * font-size: 文字大小
     * font-family: 字体样式
     */
                        font.italic ? "italic" : ""
                        , "normal"
                        , font.bold ? "bold" : ""
                        , font.size
                        , font.family
                ].join(" ");
                var lines = value.split('\n');
                var lineHeight = this.current.font.height;
                for (var i = 0;i < lines.length;i++) {
                    var tl = lines[i];
                    var x = this.current.tool.position.x, y = this.current.tool.position.y + (i + 1) * lineHeight;
                    var width = cvs.measureText(tl).width;
                    //背景色
                    if (this.current.toolValue.bgColor != "opacity" && this.current.toolValue.bgColor != "") {
                        cvs.beginPath();
                        cvs.rect(x, y - lineHeight * 0.8, width, lineHeight);
                        cvs.fillStyle = this.current.toolValue.bgColor;
                        cvs.fill();
                        cvs.closePath();
                    }

                    cvs.fillStyle = this.current.toolValue.color;
                    cvs.fillText(tl, x, y);
                    //下划线
                    if (font.underline) {
                        cvs.beginPath();
                        cvs.moveTo(x, y + lineHeight * 0.2);
                        cvs.fillStyle = this.current.toolValue.color;
                        cvs.strokeStyle = this.current.toolValue.color;
                        cvs.lineWidth = 2;
                        cvs.lineTo(x + width, y + lineHeight * 0.2);
                        cvs.stroke();
                        cvs.closePath();
                    }
                    //删除线
                    if (font.deleteline) {
                        cvs.beginPath();
                        cvs.moveTo(x, y - lineHeight * 0.2);
                        cvs.fillStyle = this.current.toolValue.color;
                        cvs.strokeStyle = this.current.toolValue.color;
                        cvs.lineWidth = 1;
                        cvs.lineTo(x + width, y - lineHeight * 0.2);
                        cvs.stroke();
                        cvs.closePath();
                    }
                }
                this.saveHistory();
            }
            ,
            //获取当前绘制图形的url
            getValue: function () {
                return this.getCVS().canvas.toDataURL("image/png");
            }
            ,
            //设置当前图形的url
            setValue: function (value, skipCanvas) {
                Vue.set(this, "myValue", value);
                if (!skipCanvas) {
                    var img = new Image(), s = this;
                    img.onload = function () {
                        var cvs = s.getCVS()
                            , canvas = cvs.canvas;
                        //保存Size
                        cvs.save();
                        cvs.drawImage(img, 0, 0, canvas.width, canvas.height);
                        //还原Size
                        cvs.restore();
                    };
                    img.src = value || defaultEmptyPNG;
                    this.current.histories.splice(0);
                    this.current.historyIndex = 0;
                    this.saveHistory();
                }
            }
            ,
            //设置当前画布图形数据(二进制)
            setData: function (value, skipMiner) {
                var cvs = this.getCVS(), s = this;
                //先清理画布
                cvs.putImageData(this.getEmptyImage(), 0, 0);
                if (value.width != cvs.canvas.width || value.height != cvs.canvas.height) {
                    var canvas = document.createElement("canvas");
                    canvas.width = value.width;
                    canvas.height = value.height;
                    var dataUrl = canvas.toDataURL("image/png");
                    var img = new Image();
                    img.width = cvs.canvas.width;
                    img.height = cvs.canvas.height;
                    img.onload = function () {
                        cvs.drawImage(img, 0, 0, img.width, img.height);
                        if (!skipMiner) {
                            s.setValue(s.getValue(), true);
                        }
                    };
                    img.src = dataUrl;
                }
                else {
                    cvs.putImageData(value || this.getEmptyImage(), 0, 0);
                    if (!skipMiner) {
                        this.setValue(this.getValue(), true);
                    }
                }
            }
            ,
            //获取当前图形数据(二进制)
            getData: function () {
                var cvs = this.getCVS();
                return cvs.getImageData(0, 0, cvs.canvas.width, cvs.canvas.height);
            },
            getEmptyImage: function () {
                var cvs = this.getCVS();
                return cvs.createImageData(cvs.canvas.width, cvs.canvas.height);
            },
            //保存历史记录(返回保存后的图形) isRestore:是否自动退回上一个效果
            saveHistory: function () {
                top.console.log(["saveHistory", new Date().toLocaleTimeString()].join("@"));
                var r = null, cvs = this.getCVS();
                r = this.getData();
                this.current.histories[this.current.historyIndex] = r;
                ++this.current.historyIndex;
                this.setValue(this.getValue(), true);
                return r;
            }
            ,
            //自动还原上一步的操作
            restoreHistoryAuto: function () {

                var idx = this.current.tool.activedHistoryIndex;
                var now = this.current.histories.length;
                top.console.log(["idx:", idx, ",now:", now].join(""));

                top.console.log(["restoreHistory", new Date().toLocaleTimeString()].join("@"));
                //弹出上一步做的内容
                if (idx >= now) {
                    if (idx <= 1)
                        r = this.getEmptyImage();
                    else
                        r = this.current.histories[idx - 1];
                    this.current.historyIndex = idx;
                }
                else {
                    //debugger
                    //历史指针始终比实际值大1
                    r = this.current.histories[now - 1 - 1];
                    --this.current.historyIndex;
                }
                this.setData(r);
            }
            , getPenPxSize: function () {
                //dpi=96 (windows 操作系统)时，1mm=4px 
                //dpi=72 (MAC 操作系统)时，1mm=?px  无此设备，请自行计算 
                /*
var $div = $("<div></div>");
$("body").append($div);
$div.css("height", "1mm");
getMm2PxRate.value = $div.height();
                */
                return this.current.toolValue.size * 4;
            }
            , "begin-pencil": function (e) {
                var pos = this.getLocation(e);
                this.beginWriteLn(pos);
            }
            , "run-pencil": function (e) {
                var pos = this.getLocation(e);
                this.writeLine(pos);
            }
            , "end-pencil": function (e) {
                var cvs = this.getCVS();
                cvs.closePath();
                this.saveHistory();
            }
            , "begin-text": function (e) {
                Vue.set(this.current.text, "value", "");
                var s = this;
                this.$nextTick(function () {
                    var ele = s.$el.querySelector("textarea.canvas-text-content");
                    if (!!ele) ele.focus();
                });
            }
            , "begin-eraser": function (e) {
                var pos = this.getLocation(e);
                var cvs = this.getCVS();
                //橡皮擦比画笔大才好擦
                //var half = this.getPenPxSize() / 2;
                var half = this.getPenPxSize();
                half = Math.ceil(half);
                cvs.clearRect(pos.x - half, pos.y - half, 2 * half, 2 * half);
            }
            , "run-eraser": function (e) {
                var pos = this.getLocation(e);
                var cvs = this.getCVS();
                //橡皮擦比画笔大才好擦
                //var half = this.getPenPxSize() / 2;
                var half = this.getPenPxSize();
                half = Math.ceil(half);
                cvs.clearRect(pos.x - half, pos.y - half, 2 * half, 2 * half);
            },
            "end-eraser": function (e) {
                this.saveHistory();
            }
            , _minimize: function (e) {
                this.useLastTool();
                Vue.set(this.current, "isPopup", false);
            }
            , _maximize: function (e) {
                Vue.set(this.current, "isPopup", true);
                var s = this;
                s.$nextTick(function () {
                    setTimeout(function () {
                        var ele = s.$el.querySelector("canvas.canvas-content");
                        var size = { width: ele.scrollWidth, height: ele.scrollHeight };
                        //保持4:3的宽高比，防止图片在不同设备上编辑导致变形
                        var roundHeight = Math.round(size.width * 3 / 4)
                        , height = Math.round(size.height);
                        if (roundHeight != height) {
                            if (roundHeight > height) {
                                //过宽了
                                size.width = Math.round(height * 400 / 3) / 100;
                            }
                            else {
                                //过高
                                size.height = Math.round(size.width * 300 / 4) / 100;
                            }
                        }
                        ele.width = size.width;
                        ele.height = size.height;
                        Vue.set(s.current.canvas.size, "width", size.width);
                        Vue.set(s.current.canvas.size, "height", size.height);
                        s.resetMaxerContainerStyle();
                        var data = s.current.histories[s.current.historyIndex - 1];
                        s.setData(data, true);
                    });
                });
                {
                    this.deActiveTool(true, e);
                    if (!this.current.tool.name) {
                        var ele = this.$el.querySelector(".canvas-maxer .canvas-tool");
                        if (!!ele) {
                            trigger(ele, "click");
                        }
                    }
                }
            }
            , _remove: function () {
                this.useLastTool();
                if (trigger(this.$el, "before-remove") != false) {
                    Vue.set(this, "disposed", true);
                    trigger(this.$el, "remove");
                }
            }
            , _clear: function () {
                this.useLastTool();
                this.setData(null);
                this.saveHistory();
            }
            , _undo: function () {
                this.useLastTool();
                var idx = this.current.historyIndex;
                if (idx == 0)
                    return;
                //历史指针始终比实际大一
                --idx;
                var data = this.current.histories.slice(idx - 1, idx);
                --this.current.historyIndex;
                this.setData(!!data ? data[0] : null);
            },
            _redo: function () {
                this.useLastTool();
                var idx = this.current.historyIndex;
                var data = this.current.histories.slice(idx, idx + 1);
                if (!!data && data.length) {
                    ++this.current.historyIndex;
                    this.setData(data[0]);
                }

            }
            , resetMaxerContainerStyle: function () {
                var s = this;
                if (!!this.current.isPopup) {
                    var size = s.current.canvas.size;
                    var st= ["position:absolute;z-index:2;width:"
                        , size.width, "px;height:", size.height
                        , "px;left:calc(50% - ", size.width, "px / 2)"
                        , ";top:calc(50% - ", size.height, "px / 2)"
                    ].join("");
                    this.maxer.container.style=st
                    var ele=this.$el.querySelector(".canvas-maxer .canvas-container");
                    if(!!ele)
                        ele.setAttribute("style",st);
                }
                else {
                    var st= ["position:absolute;z-index:2;width:"
                            , s.scaleWidth, ";height:", s.scaleHeight
                            , ";left:calc(50% - ", s.scaleWidth, " / 2)"
                            , ";top:calc(50% - ", s.scaleHeight, " / 2)"
                    ].join("");
                    this.maxer.container.style=st;
                }
            }
        }
        , beforeCreate: function () {
            //此时还读不到属性
        }
        , created: function () {
            //可读到属性
            var s = this;
            this.resetMaxerContainerStyle();
            s.$nextTick(function () {
                s.setValue(s.value, true);
                this.saveHistory();
                trigger(s.$el, "render");
            });
        }
        , computed: {
        }
    });

})(Vue);
